home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / vm / ds3100.md / vmPmax.c < prev    next >
C/C++ Source or Header  |  1991-08-09  |  58KB  |  2,252 lines

  1. /* vmPmax.c -
  2.  *
  3.  *         This file contains all hardware dependent routines for the PMAX.
  4.  *
  5.  * Copyright (C) 1989 Digital Equipment Corporation.
  6.  * Permission to use, copy, modify, and distribute this software and
  7.  * its documentation for any purpose and without fee is hereby granted,
  8.  * provided that the above copyright notice appears in all copies.  
  9.  * Digital Equipment Corporation makes no representations about the
  10.  * suitability of this software for any purpose.  It is provided "as is"
  11.  * without express or implied warranty.
  12.  */
  13.  
  14. #ifndef lint
  15. static char rcsid[] = "$Header: /sprite/src/kernel/vm/ds3100.md/RCS/vmPmax.c,v 9.14 91/08/09 15:02:12 shirriff Exp $ SPRITE (DECWRL)";
  16. #endif not lint
  17.  
  18. #include <sprite.h>
  19. #include <vmPmaxConst.h>
  20. #include <vm.h>
  21. #include <vmInt.h>
  22. #include <vmMach.h>
  23. #include <vmMachInt.h>
  24. #include <list.h>
  25. #include <mach.h>
  26. #include <proc.h>
  27. #include <sched.h>
  28. #include <stdlib.h>
  29. #include <sync.h>
  30. #include <sys.h>
  31. #include <dbg.h>
  32. #include <bstring.h>
  33.  
  34. #if (MACH_MAX_NUM_PROCESSORS == 1) /* uniprocessor implementation */
  35. #undef MASTER_LOCK
  36. #undef MASTER_UNLOCK
  37. #define MASTER_LOCK(x) DISABLE_INTR()
  38. #define MASTER_UNLOCK(x) ENABLE_INTR()
  39. #else
  40.  
  41. /*
  42.  * The master lock to synchronize access to the tlb.
  43.  */
  44. static Sync_Semaphore vmMachMutex;
  45. static Sync_Semaphore *vmMachMutexPtr = &vmMachMutex;
  46.  
  47. #endif
  48.  
  49. /*----------------------------------------------------------------------
  50.  * 
  51.  *             Hardware data structures
  52.  *
  53.  *
  54.  *----------------------------------------------------------------------
  55.  */
  56.  
  57. /*
  58.  * Machine dependent flags for the flags field in the Vm_VirtAddr struct.
  59.  * We are only allowed to use the second byte of the flags.
  60.  *
  61.  *    USING_MAPPED_SEG        The parsed virtual address falls into
  62.  *                    the mapping segment.
  63.  */
  64. #define    USING_MAPPED_SEG    0x100
  65.  
  66. /*
  67.  * The maximum amount of kernel heap available.  Sprite expects the
  68.  * sum of this value and the kernel start to be the kernel end.
  69.  * Since the MIPS machines have a big hole in the address space
  70.  * we have to add 1 Gig to cover the whole.
  71.  *
  72.  * Right now the amount is set to 1 Gig + 16 Meg
  73.  */
  74. int    vmMachKernMemSize = 0x40000000 + 0x1000000;
  75.  
  76. /*
  77.  * Table of info about each physical page on the machine.
  78.  */
  79. typedef struct PhysPage {
  80.     unsigned int    user:        1,
  81.             referenced: 1,
  82.             modified:   1;
  83. } PhysPage;
  84. PhysPage    *vmMachPhysPageArr;
  85.  
  86. /*
  87.  * Kernel mappings for all possible kernel memory.  Each entry contains
  88.  * the LOW tlb entry.
  89.  */
  90. unsigned int    *vmMach_KernelTLBMap;
  91.  
  92. /*
  93.  * PID allocation data structures.  We need a list of free and active
  94.  * PIDs as well as a mapping from segment to pid and back.
  95.  */
  96. typedef struct PIDListElem {
  97.     List_Links        links;
  98.     Proc_ControlBlock    *procPtr;
  99.     int            pid;
  100.     List_Links        tlbList;
  101. } PIDListElem;
  102. static PIDListElem    pidListElems[VMMACH_NUM_PIDS];
  103.  
  104. /*
  105.  * List of free pids.
  106.  */
  107. static List_Links    freePIDListHdr;
  108. static List_Links    *freePIDList = &freePIDListHdr;
  109.  
  110. /*
  111.  * List of active pids.
  112.  */
  113. static List_Links    activePIDListHdr;
  114. static List_Links    *activePIDList = &activePIDListHdr;
  115.  
  116. /*
  117.  * Amount of physical memory.
  118.  */
  119. int    vm_NumPhysPages;
  120.  
  121. extern    Address    vmMemEnd;
  122.  
  123. /*
  124.  * A TLB hash bucket.
  125.  */
  126. typedef struct TLBHashBucket {
  127.     List_Links        links;        /* Links so can be in PID chain. */
  128.     unsigned        low;        /* The TLB low register value. */
  129.     unsigned        high;        /* The TLB high register value. */
  130. } TLBHashBucket;
  131.  
  132. /*
  133.  * The TLB hash table.
  134.  */
  135. TLBHashBucket    vmMachTLBHashTable[VMMACH_NUM_TLB_HASH_ENTRIES];
  136.  
  137. /*
  138.  * Performance counters.  The number of fields cannot
  139.  */
  140. typedef struct {
  141.     int    savedAT;
  142.     int utlbFaultCount;
  143.     int utlbHitCount;
  144.     int modFaultCount;
  145.     int modHitCount;
  146.     int slowModCount;
  147.     int numInserts;
  148.     int numCollisions;
  149.     int numProbes;
  150.     int numFound;
  151. } TLBCounters;
  152. TLBCounters *tlbCountersPtr = (TLBCounters *)(0x80000000 + VMMACH_STAT_BASE_OFFSET);
  153.  
  154. /*
  155.  * Table of TLB entries for the user has kernel pages mapped into
  156.  * their address space.  There is only one such process (the X server).
  157.  */
  158. static unsigned    userMappingTable[VMMACH_USER_MAPPING_PAGES];
  159. static int            userMapIndex;
  160. static Boolean            userMapped = FALSE;
  161. static Proc_ControlBlock    *mappedProcPtr = (Proc_ControlBlock *)NIL;
  162.  
  163. /*
  164.  * Forward declarations.
  165.  */
  166. static int GetNumPages _ARGS_((void));
  167. static void PageInvalidate _ARGS_((register Vm_VirtAddr *virtAddrPtr,
  168.     unsigned int virtPage, Boolean segDeletion));
  169. INTERNAL static void TLBHashInsert _ARGS_((int pid, unsigned page,
  170.     unsigned lowReg, unsigned hiReg));
  171. INTERNAL static void TLBHashDelete _ARGS_((int pid, unsigned page));
  172. INTERNAL static void TLBHashFlushPID _ARGS_((int pid));
  173. INTERNAL static TLBHashBucket *TLBHashFind _ARGS_((int pid, unsigned page));
  174. static ReturnStatus VmMach_Alloc _ARGS_((VmMach_SharedData *sharedData,
  175.     int regionSize, Address *addr));
  176. static void VmMach_Unalloc _ARGS_((VmMach_SharedData *sharedData,
  177.     Address addr));
  178.  
  179.  
  180. /*
  181.  * ----------------------------------------------------------------------------
  182.  *
  183.  * VmMach_BootInit --
  184.  *
  185.  *      Do hardware dependent boot time initialization.
  186.  *
  187.  * Results:
  188.  *      None.
  189.  *
  190.  * Side effects:
  191.  *      Hardware page map for the kernel is initialized.  Also the various size
  192.  *     fields are filled in.
  193.  *
  194.  * ----------------------------------------------------------------------------
  195.  */
  196. void
  197. VmMach_BootInit(pageSizePtr, pageShiftPtr, pageTableIncPtr, kernMemSizePtr,
  198.         numKernPagesPtr, maxSegsPtr, maxProcessesPtr)
  199.     int    *pageSizePtr;
  200.     int    *pageShiftPtr;
  201.     int    *pageTableIncPtr;
  202.     int    *kernMemSizePtr;
  203.     int    *numKernPagesPtr;
  204.     int    *maxSegsPtr;
  205.     int *maxProcessesPtr;
  206. {
  207.     int            numPages;
  208.  
  209. #if (MACH_MAX_NUM_PROCESSORS > 1) /* uniprocessor implementation */
  210.     Sync_SemInitDynamic(&vmMachMutex, "Vm:vmMachMutex");
  211. #endif
  212.  
  213.     /*
  214.      * Do boot time allocation.
  215.      */
  216.     vm_NumPhysPages = GetNumPages();
  217.     vmMachPhysPageArr = 
  218.         (PhysPage *)Vm_BootAlloc(sizeof(PhysPage) * vm_NumPhysPages);
  219.     bzero((char *)vmMachPhysPageArr, sizeof(PhysPage) * vm_NumPhysPages);
  220.  
  221.     numPages = (unsigned) (mach_KernEnd - VMMACH_VIRT_CACHED_START) >> 
  222.                         VMMACH_PAGE_SHIFT;
  223.     vmMach_KernelTLBMap = (unsigned *)Vm_BootAlloc(sizeof(unsigned) * numPages);
  224.     bzero((char *)vmMach_KernelTLBMap, sizeof(unsigned) * numPages);
  225.  
  226.     /*
  227.      * Return lots of sizes to the machine independent module who called us.
  228.      */
  229.     *pageSizePtr = VMMACH_PAGE_SIZE;
  230.     *pageShiftPtr = VMMACH_PAGE_SHIFT;
  231.     *pageTableIncPtr = VMMACH_PAGE_TABLE_INCREMENT;
  232.     *kernMemSizePtr = vmMachKernMemSize;
  233.     *maxProcessesPtr = VMMACH_MAX_KERN_STACKS;
  234.     *numKernPagesPtr = vm_NumPhysPages;
  235.     *maxSegsPtr = -1;
  236. }
  237.  
  238.  
  239. /*
  240.  * ----------------------------------------------------------------------------
  241.  *
  242.  * GetNumPages --
  243.  *
  244.  *     Determine how many pages of physical memory there are.
  245.  *
  246.  * Results:
  247.  *     The number of physical pages.
  248.  *
  249.  * Side effects:
  250.  *     None.
  251.  *
  252.  * ----------------------------------------------------------------------------
  253.  */
  254. static int
  255. GetNumPages()
  256. {
  257.     unsigned        page;
  258.     unsigned        maxPage;
  259.     char        temp;
  260.  
  261.     page = (((unsigned)vmMemEnd & ~VMMACH_PHYS_CACHED_START) + 
  262.                     VMMACH_PAGE_SIZE) / VMMACH_PAGE_SIZE;
  263.     maxPage = (VMMACH_PHYS_UNCACHED_START - VMMACH_PHYS_CACHED_START) /
  264.                                VMMACH_PAGE_SIZE;
  265.     for (; page < maxPage; page++) {
  266.     if (Mach_Probe(1, (page << VMMACH_PAGE_SHIFT) | 
  267.                VMMACH_PHYS_UNCACHED_START, &temp) != SUCCESS) {
  268.         break;
  269.     }
  270.     }
  271.  
  272.     printf("%d pages of memory\n", page);
  273.  
  274.     return(page);
  275. }
  276.  
  277.  
  278. /*
  279.  * ----------------------------------------------------------------------------
  280.  *
  281.  * VmMach_AllocKernSpace --
  282.  *
  283.  *     Allocate memory for machine dependent stuff in the kernels VAS.
  284.  *
  285.  * Results:
  286.  *     None.
  287.  *
  288.  * Side effects:
  289.  *     None.
  290.  *
  291.  * ----------------------------------------------------------------------------
  292.  */
  293. Address
  294. VmMach_AllocKernSpace(baseAddr)
  295.     Address    baseAddr;
  296. {
  297.     return(baseAddr);
  298. }
  299.  
  300.  
  301. /*
  302.  * ----------------------------------------------------------------------------
  303.  *
  304.  * VmMach_Init --
  305.  *
  306.  *     Initialize all virtual memory data structures.
  307.  *
  308.  * Results:
  309.  *     None.
  310.  *
  311.  * Side effects:
  312.  *     All virtual memory linked lists and arrays are initialized.
  313.  *
  314.  * ----------------------------------------------------------------------------
  315.  */
  316. /*ARGSUSED*/
  317. void
  318. VmMach_Init(firstFreePage)
  319.     int    firstFreePage;    /* Virtual page that is the first free for the 
  320.              * kernel. */
  321. {
  322.     register    int         i;
  323.  
  324.     /*
  325.      * Initialize pid lists.  0 is invalid and PID 1 is for kernel processes.
  326.      */
  327.     List_Init(freePIDList);
  328.     List_Init(activePIDList);
  329.     for (i = 2; i < VMMACH_NUM_PIDS; i++) {
  330.     List_Insert((List_Links *)&pidListElems[i], 
  331.             LIST_ATREAR(freePIDList));
  332.     pidListElems[i].pid = i;
  333.     List_Init(&pidListElems[i].tlbList);
  334.     }
  335.  
  336.     /*
  337.      * Push vmMemEnd up to the beginning of dynamic memory.
  338.      */
  339.     vmMemEnd = (Address)VMMACH_VIRT_CACHED_START;
  340.     vm_SysSegPtr->numPages = VMMACH_VIRT_CACHED_START_PAGE - 
  341.                 vm_SysSegPtr->offset;
  342.  
  343.     /*
  344.      * Mark all entries in the TLB as invalid.  
  345.      */
  346.     VmMachFlushTLB();
  347.     for (i = 0; i < VMMACH_FIRST_RAND_ENTRY; i++) {
  348.     VmMachWriteIndexedTLB(i, 0, (unsigned)VMMACH_PHYS_CACHED_START_PAGE);
  349.     }
  350.     /*
  351.      * Zero out the TLB fault counters which are in low memory.
  352.      */
  353.     bzero((char *)tlbCountersPtr, sizeof(TLBCounters));
  354. }
  355.  
  356.  
  357. /*
  358.  * ----------------------------------------------------------------------------
  359.  *
  360.  * VmMach_SegInit --
  361.  *
  362.  *      Initialize hardware dependent data for a segment.
  363.  *
  364.  * Results:
  365.  *      None.
  366.  *
  367.  * Side effects:
  368.  *      Minimum and maximum address set in the segment table entry.
  369.  *
  370.  * ----------------------------------------------------------------------------
  371.  */
  372. void
  373. VmMach_SegInit(segPtr)
  374.     Vm_Segment    *segPtr;
  375. {
  376.     /*
  377.      * Set the minimum and maximum virtual addresses for this segment to
  378.      * be as small and as big as possible respectively because things will
  379.      * be prevented from growing automatically as soon as segments run into
  380.      * each other.
  381.      */
  382.     segPtr->minAddr = (Address)0;
  383.     segPtr->maxAddr = (Address)0x7fffffff;
  384. }
  385.  
  386.  
  387. /*
  388.  *----------------------------------------------------------------------
  389.  *
  390.  * VmMach_SegExpand --
  391.  *
  392.  *    Don't have to do anything.
  393.  *
  394.  * Results:
  395.  *    None.
  396.  *
  397.  * Side effects:
  398.  *    None.
  399.  *
  400.  *----------------------------------------------------------------------
  401.  */
  402. /*ARGSUSED*/
  403. void
  404. VmMach_SegExpand(segPtr, firstPage, lastPage)
  405.     Vm_Segment    *segPtr;    /* Segment to expand. */
  406.     int        firstPage;    /* First page to add. */
  407.     int        lastPage;    /* Last page to add. */
  408. {
  409. }
  410.  
  411.  
  412. /*
  413.  * ----------------------------------------------------------------------------
  414.  *
  415.  * VmMach_SegDelete --
  416.  *
  417.  *      Don't have to do anything.
  418.  *
  419.  * Results:
  420.  *      None.
  421.  *
  422.  * Side effects:
  423.  *      None.
  424.  *
  425.  * ----------------------------------------------------------------------------
  426.  */
  427. /*ARGSUSED*/
  428. void
  429. VmMach_SegDelete(segPtr)
  430.     Vm_Segment    *segPtr;    /* Pointer to segment to free. */
  431. {
  432. }
  433.  
  434.  
  435. /*
  436.  *----------------------------------------------------------------------
  437.  *
  438.  * VmMach_ProcInit --
  439.  *
  440.  *    Initalize the machine dependent part of the VM proc info.
  441.  *
  442.  * Results:
  443.  *    None.
  444.  *
  445.  * Side effects:
  446.  *    Machine dependent proc info is initialized.
  447.  *
  448.  *----------------------------------------------------------------------
  449.  */
  450. void
  451. VmMach_ProcInit(vmPtr)
  452.     register    Vm_ProcInfo    *vmPtr;
  453. {
  454.     if (vmPtr->machPtr == (VmMach_ProcData *)NIL) {
  455.     vmPtr->machPtr = (VmMach_ProcData *)malloc(sizeof(VmMach_ProcData));
  456.     }
  457.     vmPtr->machPtr->mapSegPtr = (struct Vm_Segment *)NIL;
  458.     vmPtr->machPtr->pid = VMMACH_INV_PID;
  459.     vmPtr->machPtr->sharedData.allocVector = (int *)NIL;
  460. }
  461.  
  462.  
  463. /*
  464.  * ----------------------------------------------------------------------------
  465.  *
  466.  * VmMach_SetupContext --
  467.  *
  468.  *      Allocate a PID to the current process.
  469.  *    
  470.  * Results:
  471.  *      PID allocated.
  472.  *
  473.  * Side effects:
  474.  *      PID may be moved to end of active list and an entry may be taken off
  475.  *    of the free list.
  476.  *
  477.  * ----------------------------------------------------------------------------
  478.  */
  479. ENTRY ClientData
  480. VmMach_SetupContext(procPtr)
  481.     register    Proc_ControlBlock    *procPtr;
  482. {
  483.     VmMach_ProcData    *machPtr;
  484.     PIDListElem        *pidPtr;
  485.  
  486.     MASTER_LOCK(vmMachMutexPtr);
  487.  
  488.     machPtr = procPtr->vmPtr->machPtr;
  489.     if (procPtr->genFlags & (PROC_KERNEL | PROC_NO_VM)) {
  490.     /*
  491.      * This is a kernel process or a process that is exiting.  These
  492.      * processes use the kernel's pid.
  493.      */
  494.     machPtr->pid = VMMACH_KERN_PID;
  495.     VmMachSetPID(VMMACH_KERN_PID);
  496.     MASTER_UNLOCK(vmMachMutexPtr);
  497.     return((ClientData)machPtr->pid);
  498.     } 
  499.  
  500.     if (machPtr->pid == VMMACH_INV_PID) {
  501.     /*
  502.      * Allocate us a new PID.
  503.      */
  504.     if (List_IsEmpty(freePIDList)) {
  505.         vmStat.machDepStat.stealPID++;
  506.         pidPtr = (PIDListElem *)List_First(activePIDList);
  507.         pidPtr->procPtr->vmPtr->machPtr->pid = VMMACH_INV_PID;
  508.         VmMachFlushPIDFromTLB(pidPtr->pid);
  509.         TLBHashFlushPID(pidPtr->pid);
  510.     } else {
  511.         pidPtr = (PIDListElem *)List_First(freePIDList);
  512.     }
  513.     machPtr->pid = pidPtr->pid;
  514.     pidPtr->procPtr = procPtr;
  515.     } else {
  516.     pidPtr = &pidListElems[machPtr->pid];
  517.     }
  518.     /*
  519.      * Move the PID to the end of the PID list and set the hardware PID
  520.      * entry.
  521.      */
  522.     List_Move((List_Links *)pidPtr, LIST_ATREAR(activePIDList));
  523.     VmMachSetPID(machPtr->pid);
  524.  
  525.     MASTER_UNLOCK(vmMachMutexPtr);
  526.     return((ClientData)machPtr->pid);
  527. }
  528.  
  529.  
  530. /*
  531.  * ----------------------------------------------------------------------------
  532.  *
  533.  * Vm_FreeContext --
  534.  *
  535.  *      Release the PID for the current process and flush the TLB for this
  536.  *    PID.
  537.  *
  538.  * Results:
  539.  *      None.
  540.  *
  541.  * Side effects:
  542.  *      PID entry moved from active list to free list and TLB flushed for
  543.  *    the PID.
  544.  *
  545.  * ----------------------------------------------------------------------------
  546.  */
  547. ENTRY void
  548. VmMach_FreeContext(procPtr)
  549.     register    Proc_ControlBlock    *procPtr;
  550. {
  551.     PIDListElem        *pidPtr;
  552.     VmMach_ProcData    *machPtr;
  553.  
  554.     MASTER_LOCK(vmMachMutexPtr);
  555.  
  556.     machPtr = procPtr->vmPtr->machPtr;
  557.     if (machPtr->pid == VMMACH_INV_PID || machPtr->pid == VMMACH_KERN_PID) {
  558.     machPtr->pid = VMMACH_INV_PID;
  559.     MASTER_UNLOCK(vmMachMutexPtr);
  560.     return;
  561.     }
  562.     pidPtr = &pidListElems[machPtr->pid];
  563.     List_Move((List_Links *)pidPtr, LIST_ATREAR(freePIDList));
  564.     VmMachFlushPIDFromTLB(machPtr->pid);
  565.     TLBHashFlushPID(machPtr->pid);
  566.     machPtr->pid = VMMACH_INV_PID;
  567.  
  568.     MASTER_UNLOCK(vmMachMutexPtr);
  569. }
  570.  
  571.  
  572. /*
  573.  * ----------------------------------------------------------------------------
  574.  *
  575.  * VmMach_ReinitContext --
  576.  *
  577.  *    Free the current PID and set up another one.  This is called by
  578.  *    routines such as Proc_Exec that add things to the context and
  579.  *    then have to abort or start a process running with a new image.
  580.  *
  581.  * Results:
  582.  *      None.
  583.  *
  584.  * Side effects:
  585.  *      The pid value in the machine dependent VM info for the process.
  586.  *
  587.  * ----------------------------------------------------------------------------
  588.  */
  589. void
  590. VmMach_ReinitContext(procPtr)
  591.     register    Proc_ControlBlock    *procPtr;
  592. {
  593.     VmMach_FreeContext(procPtr);
  594.     (void)VmMach_SetupContext(procPtr);
  595. }
  596.  
  597.  
  598. /*
  599.  *----------------------------------------------------------------------
  600.  *
  601.  * VmMach_VirtAddrParse --
  602.  *
  603.  *    See if the given address falls into the special mapping page.
  604.  *    If so parse it for our caller.
  605.  *
  606.  * Results:
  607.  *    TRUE if the address fell into the special mapping page, FALSE
  608.  *    otherwise.
  609.  *
  610.  * Side effects:
  611.  *    *transVirtAddrPtr may be filled in.
  612.  *
  613.  *----------------------------------------------------------------------
  614.  */
  615. Boolean
  616. VmMach_VirtAddrParse(procPtr, virtAddr, transVirtAddrPtr)
  617.     Proc_ControlBlock        *procPtr;
  618.     Address            virtAddr;
  619.     register    Vm_VirtAddr    *transVirtAddrPtr;
  620. {
  621.     VmMach_ProcData    *machPtr;
  622.  
  623.     if (virtAddr >= (Address)VMMACH_MAPPED_PAGE_ADDR) {
  624.     machPtr = procPtr->vmPtr->machPtr;
  625.     /*
  626.      * The address falls into the special mapping page.  Translate
  627.      * the address back to the segment that it falls into.
  628.      */
  629.     transVirtAddrPtr->segPtr = machPtr->mapSegPtr;
  630.     transVirtAddrPtr->page = machPtr->mappedPage;
  631.     transVirtAddrPtr->offset = (unsigned)virtAddr & VMMACH_OFFSET_MASK;
  632.     transVirtAddrPtr->flags = USING_MAPPED_SEG;
  633.     transVirtAddrPtr->sharedPtr = (Vm_SegProcList *) machPtr->sharedPtr;
  634.     return(TRUE);
  635.     } else {
  636.     return(FALSE);
  637.     }
  638. }
  639.  
  640.  
  641. /*
  642.  *----------------------------------------------------------------------
  643.  *
  644.  * VmMach_CopyInProc --
  645.  *
  646.  *    Copy from another processes address space into the current address
  647.  *    space.   This is done by mapping the other processes segment into
  648.  *    the current VAS and then doing the copy.  It assumed that this 
  649.  *    routine is called with the source process locked such that its
  650.  *    VM will not go away while we are doing this copy.
  651.  *
  652.  * Results:
  653.  *    SUCCESS if the copy succeeded, SYS_ARG_NOACCESS if fromAddr is invalid.
  654.  *
  655.  * Side effects:
  656.  *    What toAddr points to is modified.
  657.  *
  658.  *----------------------------------------------------------------------
  659.  */
  660. /*ARGSUSED*/
  661. ENTRY ReturnStatus
  662. VmMach_CopyInProc(numBytes, fromProcPtr, fromAddr, virtAddrPtr,
  663.               toAddr, toKernel)
  664.     int     numBytes;        /* The maximum number of bytes to 
  665.                        copy in. */
  666.     Proc_ControlBlock    *fromProcPtr;    /* Which process to copy from.*/
  667.     Address        fromAddr;    /* The address to copy from */
  668.     Vm_VirtAddr        *virtAddrPtr;
  669.     Address        toAddr;        /* The address to copy to */
  670.     Boolean        toKernel;    /* This copy is happening to the
  671.                      * kernel's address space. */
  672. {
  673.     ReturnStatus        status = SUCCESS;
  674.     register VmMach_ProcData    *machPtr;
  675.     Proc_ControlBlock        *toProcPtr;
  676.     int                pageOffset;
  677.     int                bytesToCopy;
  678.  
  679. /*
  680.     printf("VmMach_CopyInProc: num=%x from=%x toAddr=%x toK=%d\n",
  681.         numBytes, fromAddr, toAddr, toKernel);
  682.  */
  683.     toProcPtr = Proc_GetCurrentProc();
  684.     machPtr = toProcPtr->vmPtr->machPtr;
  685.     machPtr->mapSegPtr = virtAddrPtr->segPtr;
  686.     machPtr->sharedPtr = (Address) virtAddrPtr->sharedPtr;
  687.     machPtr->mappedPage = (unsigned int) (fromAddr) >> VMMACH_PAGE_SHIFT;
  688.     /*
  689.      * Do a page worths at a time.
  690.      */
  691.     while (numBytes > 0 && status == SUCCESS) {
  692.     pageOffset = (unsigned int)fromAddr & (VMMACH_PAGE_SIZE - 1);
  693.     bytesToCopy = VMMACH_PAGE_SIZE - pageOffset;
  694.     if (bytesToCopy > numBytes) {
  695.         bytesToCopy = numBytes;
  696.     }
  697.     /*
  698.      * Do the copy.
  699.      */
  700.     toProcPtr->vmPtr->vmFlags |= VM_COPY_IN_PROGRESS;
  701.     status = VmMachDoCopy(bytesToCopy,
  702.                   (Address)(VMMACH_MAPPED_PAGE_ADDR + pageOffset),
  703.                   toAddr);
  704.     toProcPtr->vmPtr->vmFlags &= ~VM_COPY_IN_PROGRESS;
  705.  
  706.     MASTER_LOCK(vmMachMutexPtr);
  707.     TLBHashDelete(machPtr->pid, (unsigned)VMMACH_MAPPED_PAGE_NUM);
  708.     VmMachFlushPageFromTLB(machPtr->pid, (unsigned)VMMACH_MAPPED_PAGE_NUM);
  709.     MASTER_UNLOCK(vmMachMutexPtr);
  710.  
  711.     if (status == SUCCESS) {
  712.         numBytes -= bytesToCopy;
  713.         fromAddr += bytesToCopy;
  714.         toAddr += bytesToCopy;
  715.     } else {
  716.         status = SYS_ARG_NOACCESS;
  717.     }
  718.     machPtr->mappedPage++;
  719.     }
  720.     machPtr->mapSegPtr = (struct Vm_Segment *)NIL;
  721.     return(status);
  722. }
  723.  
  724.  
  725. /*
  726.  *----------------------------------------------------------------------
  727.  *
  728.  * VmMach_CopyOutProc --
  729.  *
  730.  *    Copy from the current VAS to another processes VAS.  This is done by 
  731.  *    mapping the other processes segment into the current VAS and then 
  732.  *    doing the copy.  It assumed that this routine is called with the dest
  733.  *    process locked such that its VM will not go away while we are doing
  734.  *    the copy.
  735.  *
  736.  * Results:
  737.  *    SUCCESS if the copy succeeded, SYS_ARG_NOACCESS if fromAddr is invalid.
  738.  *
  739.  * Side effects:
  740.  *    What toAddr points to is modified.
  741.  *
  742.  *----------------------------------------------------------------------
  743.  */
  744. /*ARGSUSED*/
  745. ENTRY ReturnStatus
  746. VmMach_CopyOutProc(numBytes, fromAddr, fromKernel, toProcPtr, toAddr,
  747.            virtAddrPtr)
  748.     int         numBytes;    /* The maximum number of bytes to 
  749.                        copy in. */
  750.     Address        fromAddr;    /* The address to copy from */
  751.     Boolean        fromKernel;    /* This copy is happening to the
  752.                      * kernel's address space. */
  753.     Proc_ControlBlock    *toProcPtr;    /* Which process to copy from.*/
  754.     Address        toAddr;        /* The address to copy to */
  755.     Vm_VirtAddr        *virtAddrPtr;
  756. {
  757.     ReturnStatus        status = SUCCESS;
  758.     register VmMach_ProcData    *machPtr;
  759.     Proc_ControlBlock        *fromProcPtr;
  760.     int                pageOffset;
  761.     int                bytesToCopy;
  762.  
  763.  
  764. /*
  765.     printf("VmMach_CopyOutProc: num=%x from=%x fromK=%d toAddr=%x\n",
  766.         numBytes, fromAddr, fromKernel, toAddr);
  767.  */
  768.     fromProcPtr = Proc_GetCurrentProc();
  769.     machPtr = fromProcPtr->vmPtr->machPtr;
  770.     machPtr->mapSegPtr = virtAddrPtr->segPtr;
  771.     machPtr->mappedPage = (unsigned int) (toAddr) >> VMMACH_PAGE_SHIFT;
  772.     machPtr->sharedPtr = (Address) virtAddrPtr->sharedPtr;
  773.     /*
  774.      * Do a hardware segments worth at a time until done.
  775.      */
  776.     while (numBytes > 0 && status == SUCCESS) {
  777.     pageOffset = (unsigned)toAddr & (VMMACH_PAGE_SIZE - 1);
  778.     bytesToCopy = VMMACH_PAGE_SIZE - pageOffset;
  779.     if (bytesToCopy > numBytes) {
  780.         bytesToCopy = numBytes;
  781.     }
  782.     /*
  783.      * Do the copy.
  784.      */
  785.     fromProcPtr->vmPtr->vmFlags |= VM_COPY_IN_PROGRESS;
  786.     status = VmMachDoCopy(bytesToCopy, fromAddr,
  787.                   (Address) (VMMACH_MAPPED_PAGE_ADDR + pageOffset));
  788.     fromProcPtr->vmPtr->vmFlags &= ~VM_COPY_IN_PROGRESS;
  789.  
  790.     MASTER_LOCK(vmMachMutexPtr);
  791.     TLBHashDelete(machPtr->pid, (unsigned)VMMACH_MAPPED_PAGE_NUM);
  792.     VmMachFlushPageFromTLB(machPtr->pid, (unsigned)VMMACH_MAPPED_PAGE_NUM);
  793.     MASTER_UNLOCK(vmMachMutexPtr);
  794.  
  795.     if (status == SUCCESS) {
  796.         numBytes -= bytesToCopy;
  797.         fromAddr += bytesToCopy;
  798.         toAddr += bytesToCopy;
  799.     } else {
  800.         status = SYS_ARG_NOACCESS;
  801.     }
  802.  
  803.     machPtr->mappedPage++;
  804.     }
  805.     machPtr->mapSegPtr = (struct Vm_Segment *)NIL;
  806.     return(status);
  807. }
  808.  
  809.  
  810. /*
  811.  *----------------------------------------------------------------------
  812.  *
  813.  * VmMach_SetSegProt --
  814.  *
  815.  *    Change the protection in the page table for the given range of bytes
  816.  *    for the given segment.
  817.  *
  818.  * Results:
  819.  *    None.
  820.  *
  821.  * Side effects:
  822.  *    Page table may be modified for the segment.
  823.  *
  824.  *----------------------------------------------------------------------
  825.  */
  826. ENTRY void
  827. VmMach_SetSegProt(segPtr, firstPage, lastPage, makeWriteable)
  828.     register Vm_Segment        *segPtr;    /* Segment to change protection
  829.                            for. */
  830.     register int        firstPage;  /* First page to set protection
  831.                          * for. */
  832.     int                lastPage;   /* First page to set protection
  833.                          * for. */
  834.     Boolean            makeWriteable;/* TRUE => make the pages 
  835.                            *     writable.
  836.                            * FALSE => make readable only.*/
  837. {
  838.  
  839.     VmProcLink        *procLinkPtr;
  840.     int            i;
  841.     TLBHashBucket    *bucketPtr;
  842.  
  843.     MASTER_LOCK(vmMachMutexPtr);
  844.  
  845.     if (!makeWriteable || segPtr->type == VM_CODE) {
  846.     VmMachFlushTLB();
  847.     }
  848.  
  849.     LIST_FORALL(segPtr->procList, (List_Links *) procLinkPtr) {
  850.     for (i = firstPage; i <= lastPage; i++) {
  851.         bucketPtr= TLBHashFind(procLinkPtr->procPtr->vmPtr->machPtr->pid,
  852.                    (unsigned)i);
  853.         if (bucketPtr != (TLBHashBucket *)NIL) {
  854.         if (makeWriteable) {
  855.             bucketPtr->low |= VMMACH_TLB_ENTRY_WRITEABLE;
  856.         } else {
  857.             bucketPtr->low &= ~VMMACH_TLB_ENTRY_WRITEABLE;
  858.         }
  859. #ifdef notdef
  860.         if (segPtr->type == VM_CODE) {
  861.             bucketPtr->low |= VMMACH_TLB_NON_CACHEABLE_BIT;
  862.         }
  863. #endif
  864.         }
  865.     }
  866.     }
  867.  
  868.     MASTER_UNLOCK(vmMachMutexPtr);
  869. }
  870.  
  871.  
  872. /*
  873.  *----------------------------------------------------------------------
  874.  *
  875.  * VmMach_FlushCode --
  876.  *
  877.  *    Flush the specified address range from the instruction cache.
  878.  *
  879.  * Results:
  880.  *    None.
  881.  *
  882.  * Side effects:
  883.  *    Code is flushed from the cache.
  884.  *
  885.  *----------------------------------------------------------------------
  886.  */
  887. /*ARGSUSED*/
  888. void
  889. VmMach_FlushCode(procPtr, virtAddrPtr, physPage, numBytes)
  890.     Proc_ControlBlock    *procPtr;
  891.     Vm_VirtAddr        *virtAddrPtr;
  892.     unsigned        physPage;
  893.     int            numBytes;
  894. {
  895.     Mach_FlushCode((Address)((physPage << VMMACH_PAGE_SHIFT) +
  896.         virtAddrPtr->offset), (unsigned)numBytes);
  897. }
  898.  
  899.  
  900. /*
  901.  *----------------------------------------------------------------------
  902.  *
  903.  * VmMach_SetPageProt --
  904.  *
  905.  *    Set the protection in hardware and software for the given virtual
  906.  *    page.  
  907.  *
  908.  *    IMPORTANT: We assume that we have access to the list of processes
  909.  *           that are using this segment (i.e. the caller has the
  910.  *           virtual memory monitor lock down).
  911.  *
  912.  * Results:
  913.  *    None.
  914.  *
  915.  * Side effects:
  916.  *    Page table may be modified for the segment.
  917.  *
  918.  *----------------------------------------------------------------------
  919.  */
  920. ENTRY void
  921. VmMach_SetPageProt(virtAddrPtr, softPTE)
  922.     register    Vm_VirtAddr    *virtAddrPtr;    /* The virtual page to set the
  923.                          * protection for.*/
  924.     Vm_PTE            softPTE;    /* Software pte. */
  925. {
  926.     Vm_Segment        *segPtr;
  927.     VmProcLink        *procLinkPtr;
  928.     int            pid;
  929.     TLBHashBucket    *bucketPtr;
  930.  
  931.     MASTER_LOCK(vmMachMutexPtr);
  932.  
  933.     segPtr = virtAddrPtr->segPtr;
  934.     if (softPTE & (VM_COW_BIT | VM_READ_ONLY_PROT)) {
  935.     LIST_FORALL(segPtr->procList, (List_Links *) procLinkPtr) {
  936.         pid = procLinkPtr->procPtr->vmPtr->machPtr->pid;
  937.         (void) VmMachClearTLBModBit(pid, virtAddrPtr->page);
  938.         bucketPtr = TLBHashFind(pid, (unsigned)virtAddrPtr->page);
  939.         if (bucketPtr != (TLBHashBucket *)NIL) {
  940.         bucketPtr->low &= ~VMMACH_TLB_MOD_BIT;
  941.         }
  942.         bucketPtr = TLBHashFind(pid, (unsigned)virtAddrPtr->page);
  943.         if (bucketPtr != (TLBHashBucket *)NIL) {
  944.         bucketPtr->low &= ~VMMACH_TLB_ENTRY_WRITEABLE;
  945.         }
  946.     }
  947.     } else {
  948.     LIST_FORALL(segPtr->procList, (List_Links *) procLinkPtr) {
  949.         bucketPtr = TLBHashFind(procLinkPtr->procPtr->vmPtr->machPtr->pid,
  950.                     (unsigned)virtAddrPtr->page);
  951.         if (bucketPtr != (TLBHashBucket *)NIL) {
  952.         bucketPtr->low |= VMMACH_TLB_ENTRY_WRITEABLE;
  953.         }
  954.     }
  955.     }
  956.  
  957.     MASTER_UNLOCK(vmMachMutexPtr);
  958. }
  959.  
  960.  
  961. /*
  962.  * ----------------------------------------------------------------------------
  963.  *
  964.  * VmMach_AllocCheck --
  965.  *
  966.  *      Determine if this page can be reallocated.  A page can be reallocated
  967.  *    if it has not been referenced or modified.
  968.  *  
  969.  * Results:
  970.  *      None.
  971.  *
  972.  * Side effects:
  973.  *      The given page will be invalidated in the hardware if it has not
  974.  *    been referenced and *refPtr and *modPtr will have the hardware 
  975.  *    reference and modify bits or'd in.
  976.  *
  977.  * ----------------------------------------------------------------------------
  978.  */
  979. ENTRY void
  980. VmMach_AllocCheck(virtAddrPtr, virtFrameNum, refPtr, modPtr)
  981.     register    Vm_VirtAddr    *virtAddrPtr;
  982.     unsigned    int        virtFrameNum;
  983.     register    Boolean        *refPtr;
  984.     register    Boolean        *modPtr;
  985. {
  986.     Boolean    origMod;
  987.  
  988.     MASTER_LOCK(vmMachMutexPtr);
  989.  
  990.     origMod = *modPtr;
  991.  
  992.     *refPtr |= vmMachPhysPageArr[virtFrameNum].referenced;
  993.     *modPtr = vmMachPhysPageArr[virtFrameNum].modified;
  994.     if (!*refPtr) {
  995.     /*
  996.      * Invalidate the page so that it will force a fault if it is
  997.      * referenced.  Since our caller has blocked all faults on this
  998.      * page, by invalidating it we can guarantee that the reference and
  999.      * modify information that we are returning will be valid until
  1000.      * our caller reenables faults on this page.
  1001.      */
  1002.     PageInvalidate(virtAddrPtr, virtFrameNum, FALSE);
  1003.  
  1004.     if (origMod && !*modPtr) {
  1005.         /*
  1006.          * This page had the modify bit set in software but not in
  1007.          * hardware.
  1008.          */
  1009.         vmStat.notHardModPages++;
  1010.     }
  1011.     }
  1012.     *modPtr |= origMod;
  1013.  
  1014.     MASTER_UNLOCK(vmMachMutexPtr);
  1015. }
  1016.  
  1017.  
  1018. /*
  1019.  * ----------------------------------------------------------------------------
  1020.  *
  1021.  * VmMach_GetRefModBits --
  1022.  *
  1023.  *      Pull the reference and modified bits out of hardware.
  1024.  *  
  1025.  * Results:
  1026.  *      None.
  1027.  *
  1028.  * Side effects:
  1029.  *      
  1030.  *
  1031.  * ----------------------------------------------------------------------------
  1032.  */
  1033. /*ARGSUSED*/
  1034. ENTRY void
  1035. VmMach_GetRefModBits(virtAddrPtr, virtFrameNum, refPtr, modPtr)
  1036.     Vm_VirtAddr            *virtAddrPtr;
  1037.     unsigned    int        virtFrameNum;
  1038.     register    Boolean        *refPtr;
  1039.     register    Boolean        *modPtr;
  1040. {
  1041.     MASTER_LOCK(vmMachMutexPtr);
  1042.  
  1043.     *refPtr = vmMachPhysPageArr[virtFrameNum].referenced;
  1044.     *modPtr = vmMachPhysPageArr[virtFrameNum].modified;
  1045.  
  1046.     MASTER_UNLOCK(vmMachMutexPtr);
  1047. }
  1048.  
  1049.  
  1050. /*
  1051.  * ----------------------------------------------------------------------------
  1052.  *
  1053.  * VmMach_ClearRefBit --
  1054.  *
  1055.  *      Clear the reference bit at the given virtual address.
  1056.  *
  1057.  * Results:
  1058.  *      None.
  1059.  *
  1060.  * Side effects:
  1061.  *      Hardware reference bit cleared.
  1062.  *
  1063.  * ----------------------------------------------------------------------------
  1064.  */
  1065. /*ARGSUSED*/
  1066. ENTRY void
  1067. VmMach_ClearRefBit(virtAddrPtr, virtFrameNum)
  1068.     Vm_VirtAddr        *virtAddrPtr;
  1069.     unsigned     int    virtFrameNum;
  1070. {
  1071.     MASTER_LOCK(vmMachMutexPtr);
  1072.  
  1073.     vmMachPhysPageArr[virtFrameNum].referenced = 0;
  1074.  
  1075.     MASTER_UNLOCK(vmMachMutexPtr);
  1076. }
  1077.  
  1078.  
  1079. /*
  1080.  * ----------------------------------------------------------------------------
  1081.  *
  1082.  * VmMach_ClearModBit --
  1083.  *
  1084.  *      Clear the modified bit at the given virtual address.
  1085.  *
  1086.  * Results:
  1087.  *      None.
  1088.  *
  1089.  * Side effects:
  1090.  *      Hardware modified bit cleared.
  1091.  *
  1092.  * ----------------------------------------------------------------------------
  1093.  */
  1094. ENTRY void
  1095. VmMach_ClearModBit(virtAddrPtr, virtFrameNum)
  1096.     register    Vm_VirtAddr    *virtAddrPtr;
  1097.     unsigned    int        virtFrameNum;
  1098. {
  1099.     register    Vm_Segment    *segPtr;
  1100.     VmProcLink            *procLinkPtr;
  1101.     int                pid;
  1102.     TLBHashBucket        *hashBucketPtr;
  1103.  
  1104.     MASTER_LOCK(vmMachMutexPtr);
  1105.  
  1106.     vmMachPhysPageArr[virtFrameNum].modified = 0;
  1107.  
  1108.     segPtr = virtAddrPtr->segPtr;
  1109.     LIST_FORALL(segPtr->procList, (List_Links *) procLinkPtr) {
  1110.     pid = procLinkPtr->procPtr->vmPtr->machPtr->pid;
  1111.     (void) VmMachClearTLBModBit(pid, virtAddrPtr->page);
  1112.     hashBucketPtr = TLBHashFind(pid, (unsigned)virtAddrPtr->page);
  1113.     if (hashBucketPtr != (TLBHashBucket *)NIL) {
  1114.         hashBucketPtr->low &= ~VMMACH_TLB_MOD_BIT;
  1115.     }
  1116.     }
  1117.  
  1118.     MASTER_UNLOCK(vmMachMutexPtr);
  1119. }
  1120.  
  1121.  
  1122. /*
  1123.  * ----------------------------------------------------------------------------
  1124.  *
  1125.  * VmMach_PageValidate --
  1126.  *
  1127.  *      Validate a page for the given virtual address.  It is assumed that when
  1128.  *      this routine is called that the pid register contains the pid in which
  1129.  *    this page will be validated.
  1130.  *
  1131.  * Results:
  1132.  *      None.
  1133.  *
  1134.  * Side effects:
  1135.  *      The page table and hardware segment tables associated with the segment
  1136.  *      are modified to validate the page.
  1137.  *
  1138.  * ----------------------------------------------------------------------------
  1139.  */
  1140. ENTRY void
  1141. VmMach_PageValidate(virtAddrPtr, pte) 
  1142.     register    Vm_VirtAddr    *virtAddrPtr;
  1143.     Vm_PTE            pte;
  1144. {
  1145.     Proc_ControlBlock    *procPtr;
  1146.     VmMach_ProcData    *machPtr;
  1147.     unsigned        lowEntry;
  1148.     unsigned        virtPage;
  1149.     int            retVal;
  1150.     int            page;
  1151.  
  1152.     MASTER_LOCK(vmMachMutexPtr);
  1153.  
  1154.     procPtr = Proc_GetCurrentProc();
  1155.     machPtr = procPtr->vmPtr->machPtr;
  1156.     if (machPtr->pid == 0) {
  1157.     VmMach_ReinitContext(procPtr);
  1158.     }
  1159.  
  1160.     /*
  1161.      * Set up the TLB entry and the physical page info.
  1162.      */
  1163.     if (virtAddrPtr->segPtr == vm_SysSegPtr) {
  1164.     lowEntry = ((pte & VM_PAGE_FRAME_FIELD) << VMMACH_TLB_PHYS_PAGE_SHIFT)| 
  1165.             VMMACH_TLB_VALID_BIT | VMMACH_TLB_GLOBAL_BIT | 
  1166.             VMMACH_TLB_MOD_BIT;
  1167.     retVal = VmMachWriteTLB(lowEntry,
  1168.           (unsigned) ((virtAddrPtr->page << VMMACH_TLB_VIRT_PAGE_SHIFT) | 
  1169.                (VMMACH_KERN_PID << VMMACH_TLB_PID_SHIFT)));
  1170.     if (retVal >= 0) {
  1171.         panic("VmMach_PageValidate: Kern TLB entry found\n");
  1172.     }
  1173.     page = virtAddrPtr->page - VMMACH_VIRT_CACHED_START_PAGE;
  1174.     if (page >= 0) {
  1175.         vmMach_KernelTLBMap[page] = lowEntry;
  1176.     }
  1177.     } else {
  1178.     unsigned    highEntry;
  1179.  
  1180.     vmMachPhysPageArr[pte & VM_PAGE_FRAME_FIELD].user = 1;
  1181.     lowEntry = ((pte & VM_PAGE_FRAME_FIELD) << 
  1182.                 VMMACH_TLB_PHYS_PAGE_SHIFT) | 
  1183.             VMMACH_TLB_VALID_BIT;
  1184.     if (!(pte & (VM_COW_BIT | VM_READ_ONLY_PROT)) && !(virtAddrPtr->flags
  1185.         & VM_READONLY_SEG)) {
  1186.         lowEntry |= VMMACH_TLB_ENTRY_WRITEABLE;
  1187.     }
  1188.     if (virtAddrPtr->flags & USING_MAPPED_SEG) {
  1189.         virtPage = VMMACH_MAPPED_PAGE_NUM;
  1190.     } else {
  1191.         virtPage = virtAddrPtr->page;
  1192.     }
  1193.     if (machPtr->modPage == virtPage) {
  1194.         /*
  1195.          * We are validating after a TLB modified fault so set the modify
  1196.          * bit.
  1197.          */
  1198.         lowEntry |= VMMACH_TLB_MOD_BIT;
  1199.         vmMachPhysPageArr[pte & VM_PAGE_FRAME_FIELD].modified = 1;
  1200.     }
  1201.  
  1202.     highEntry = (virtPage << VMMACH_TLB_VIRT_PAGE_SHIFT) |
  1203.             (machPtr->pid << VMMACH_TLB_PID_SHIFT);
  1204.     TLBHashInsert(machPtr->pid, virtPage, lowEntry, highEntry);
  1205.     retVal = VmMachWriteTLB(lowEntry, highEntry);
  1206.     if (retVal >= 0 && !(machPtr->modPage == virtPage)) {
  1207.         panic("VmMach_PageValidate: Non-modified user TLB entry found\n");
  1208.     }
  1209.     }
  1210.  
  1211.     MASTER_UNLOCK(vmMachMutexPtr);
  1212. }
  1213.  
  1214.  
  1215. /*
  1216.  * ----------------------------------------------------------------------------
  1217.  *
  1218.  * PageInvalidate --
  1219.  *
  1220.  *      Invalidate a page for the given segment.  
  1221.  *
  1222.  * Results:
  1223.  *      None.
  1224.  *
  1225.  * Side effects:
  1226.  *      The page table and hardware tables associated with the segment
  1227.  *      are modified to invalidate the page.
  1228.  *
  1229.  * ----------------------------------------------------------------------------
  1230.  */
  1231. /*ARGSUSED*/
  1232. INTERNAL static void
  1233. PageInvalidate(virtAddrPtr, virtPage, segDeletion) 
  1234.     register    Vm_VirtAddr    *virtAddrPtr;
  1235.     unsigned     int        virtPage;
  1236.     Boolean            segDeletion;
  1237. {
  1238.     PhysPage        *physPagePtr;
  1239.  
  1240.     physPagePtr = &vmMachPhysPageArr[virtPage];
  1241.     if ((physPagePtr->user && virtAddrPtr->segPtr != vm_SysSegPtr) ||
  1242.         !physPagePtr->user) {
  1243.     /*
  1244.      * Clear out reference and modified info for this page.  We can
  1245.      * only clear it if one of two conditions hold:
  1246.      *
  1247.      *    1) It has been validated in a user's address space and
  1248.      *       is now being invalidated from a user's address space.
  1249.      *    2) It has never been validated in a user's address space.
  1250.      *
  1251.      * We have to make this distinction because a page can be mapped
  1252.      * both by a user and the kernel at the same time and we need to
  1253.      * make sure that the kernel invalidation doesn't wipe out good
  1254.      * user reference and modify information.
  1255.      */
  1256.     physPagePtr->user = 0;
  1257.     physPagePtr->referenced = 0;
  1258.     physPagePtr->modified = 0;
  1259.     }
  1260.  
  1261.     if (virtAddrPtr->segPtr == vm_SysSegPtr) {
  1262.     int    page;
  1263.  
  1264.     page = virtAddrPtr->page - VMMACH_VIRT_CACHED_START_PAGE;
  1265.     if (page >= 0) {
  1266.         vmMach_KernelTLBMap[page] = 0;
  1267.     }
  1268.     (void) VmMachFlushPageFromTLB(VMMACH_KERN_PID, 
  1269.                       (unsigned)virtAddrPtr->page);
  1270.     } else {
  1271.     VmProcLink    *procLinkPtr;
  1272.     int        pid;
  1273.  
  1274.     /*
  1275.      * Flush the page from all pids.
  1276.      */
  1277.     LIST_FORALL(virtAddrPtr->segPtr->procList, (List_Links *) procLinkPtr) {
  1278.         pid = procLinkPtr->procPtr->vmPtr->machPtr->pid;
  1279.         (void) VmMachFlushPageFromTLB(pid, (unsigned)virtAddrPtr->page);
  1280.         TLBHashDelete(pid, (unsigned)virtAddrPtr->page);
  1281.     }
  1282.     if (virtAddrPtr->segPtr->type == VM_CODE) {
  1283.         /*
  1284.          * If a code page flush it from the instruction cache.
  1285.          */
  1286.         Mach_FlushCode((Address)(virtPage << VMMACH_PAGE_SHIFT),
  1287.             VMMACH_PAGE_SIZE);
  1288.     }
  1289.     }
  1290. }
  1291.  
  1292.  
  1293. /*
  1294.  * ----------------------------------------------------------------------------
  1295.  *
  1296.  * VmMach_PageInvalidate --
  1297.  *
  1298.  *      Invalidate a page for the given segment.  
  1299.  *
  1300.  * Results:
  1301.  *      None.
  1302.  *
  1303.  * Side effects:
  1304.  *      The page table and hardware segment tables associated with the segment
  1305.  *      are modified to invalidate the page.
  1306.  *
  1307.  * ----------------------------------------------------------------------------
  1308.  */
  1309. ENTRY void
  1310. VmMach_PageInvalidate(virtAddrPtr, virtPage, segDeletion) 
  1311.     register    Vm_VirtAddr    *virtAddrPtr;
  1312.     unsigned     int        virtPage;
  1313.     Boolean            segDeletion;
  1314. {
  1315.     MASTER_LOCK(vmMachMutexPtr);
  1316.  
  1317.     PageInvalidate(virtAddrPtr, virtPage, segDeletion);
  1318.  
  1319.     MASTER_UNLOCK(vmMachMutexPtr);
  1320. }
  1321.  
  1322.  
  1323. /*
  1324.  *----------------------------------------------------------------------
  1325.  *
  1326.  * VmMach_PinUserPages --
  1327.  *
  1328.  *    Force a user page to be resident in memory.
  1329.  *
  1330.  * Results:
  1331.  *    None.
  1332.  *
  1333.  * Side effects:
  1334.  *    None.
  1335.  *
  1336.  *----------------------------------------------------------------------
  1337.  */
  1338. /*ARGSUSED*/
  1339. void
  1340. VmMach_PinUserPages(mapType, virtAddrPtr, lastPage)
  1341.     int        mapType;
  1342.     Vm_VirtAddr    *virtAddrPtr;
  1343.     int        lastPage;
  1344. {
  1345. }
  1346.  
  1347.  
  1348. /*
  1349.  *----------------------------------------------------------------------
  1350.  *
  1351.  * VmMach_UnpinUserPages --
  1352.  *
  1353.  *    Allow a page that was pinned to be unpinned.
  1354.  *
  1355.  * Results:
  1356.  *    None.
  1357.  *
  1358.  * Side effects:
  1359.  *    None.
  1360.  *
  1361.  *----------------------------------------------------------------------
  1362.  */
  1363. /*ARGSUSED*/
  1364. ENTRY void
  1365. VmMach_UnpinUserPages(virtAddrPtr, lastPage)
  1366.     Vm_VirtAddr    *virtAddrPtr;
  1367.     int        lastPage;
  1368. {
  1369. }
  1370.  
  1371.  
  1372. /*
  1373.  *----------------------------------------------------------------------
  1374.  *
  1375.  * VmMach_FlushPage --
  1376.  *
  1377.  *    Flush the page at the given virtual address from all caches.  We
  1378.  *    don't have to do anything on the Sun-2 and Sun-3 workstations
  1379.  *    that we have.
  1380.  *
  1381.  * Results:
  1382.  *    None.
  1383.  *
  1384.  * Side effects:
  1385.  *    The given page is flushed from the caches.
  1386.  *
  1387.  *----------------------------------------------------------------------
  1388.  */
  1389. /*ARGSUSED*/
  1390. void
  1391. VmMach_FlushPage(virtAddrPtr, invalidate)
  1392.     Vm_VirtAddr    *virtAddrPtr;
  1393.     Boolean    invalidate;    /* Should invalidate the pte after flushing. */
  1394. {
  1395. }
  1396.  
  1397.  
  1398. /*
  1399.  *----------------------------------------------------------------------
  1400.  *
  1401.  * VmMach_HandleSegMigration --
  1402.  *
  1403.  *    Handle machine-dependent aspects of segment preparation for migration.
  1404.  *    There's nothing to do on this machine.
  1405.  *
  1406.  * Results:
  1407.  *    None.
  1408.  *
  1409.  * Side effects:
  1410.  *    None.
  1411.  *
  1412.  *----------------------------------------------------------------------
  1413.  */
  1414. /*ARGSUSED*/
  1415. void
  1416. VmMach_HandleSegMigration(segPtr)
  1417.     Vm_Segment    *segPtr;
  1418. {
  1419.     return;
  1420. }
  1421.  
  1422.  
  1423.  
  1424. /*
  1425.  *----------------------------------------------------------------------
  1426.  *
  1427.  * VmMach_Cmd --
  1428.  *
  1429.  *    Machine dependent vm commands.
  1430.  *
  1431.  * Results:
  1432.  *    None.
  1433.  *
  1434.  * Side effects:
  1435.  *    None.
  1436.  *
  1437.  *----------------------------------------------------------------------
  1438.  */
  1439. /*ARGSUSED*/
  1440. ReturnStatus
  1441. VmMach_Cmd(command, arg)
  1442.     int    command;
  1443.     int arg;
  1444. {
  1445.     return(GEN_INVALID_ARG);
  1446. }
  1447.  
  1448.  
  1449.  
  1450. /*
  1451.  *----------------------------------------------------------------------
  1452.  *
  1453.  * VmMach_TLBFault --
  1454.  *
  1455.  *    Handle a TLB fault.
  1456.  *
  1457.  * Results:
  1458.  *    None.
  1459.  *
  1460.  * Side effects:
  1461.  *    None.
  1462.  *
  1463.  *----------------------------------------------------------------------
  1464.  */
  1465. ENTRY ReturnStatus
  1466. VmMach_TLBFault(virtAddr)
  1467.     Address    virtAddr;
  1468. {
  1469.  
  1470.     if (virtAddr >= (Address)VMMACH_VIRT_CACHED_START &&
  1471.         virtAddr < (Address)VMMACH_MAPPED_PAGE_ADDR) {
  1472.     dprintf("fault 1\n");
  1473.     return(FAILURE);
  1474.     } else if (virtAddr >= (Address)VMMACH_USER_MAPPING_BASE_ADDR &&
  1475.            virtAddr < (Address)VMMACH_PHYS_CACHED_START) {
  1476.     /*
  1477.      * This address falls into the range of address that are used to
  1478.      * map kernel pages into a user's address space.
  1479.      */
  1480.     unsigned virtPage, lowEntry, highEntry;
  1481.     int pid;
  1482.  
  1483.     if (Proc_GetCurrentProc() != mappedProcPtr) {
  1484.         dprintf("fault 2\n");
  1485.         return(FAILURE);
  1486.     }
  1487.     pid = mappedProcPtr->vmPtr->machPtr->pid;
  1488.     virtPage = (unsigned)virtAddr >> VMMACH_PAGE_SHIFT;
  1489.  
  1490.  
  1491.     lowEntry = userMappingTable[virtPage - VMMACH_USER_MAPPING_BASE_PAGE];
  1492.     if (lowEntry == 0) {
  1493.         dprintf("fault 3\n");
  1494.         return(FAILURE);
  1495.     }
  1496.     highEntry = (virtPage << VMMACH_TLB_VIRT_PAGE_SHIFT) |
  1497.             (pid << VMMACH_TLB_PID_SHIFT);
  1498.  
  1499.     MASTER_LOCK(vmMachMutexPtr);
  1500.     TLBHashInsert(pid, virtPage, lowEntry, highEntry);
  1501.     (void)VmMachWriteTLB(lowEntry, highEntry);
  1502.     MASTER_UNLOCK(vmMachMutexPtr);
  1503.  
  1504.     return(SUCCESS);
  1505.     } else {
  1506.     ReturnStatus status;
  1507.     status = Vm_PageIn(virtAddr, FALSE);
  1508.     if (status != SUCCESS) {
  1509.         dprintf("fault 4\n");
  1510.     }
  1511.     return status;
  1512.     /*
  1513.     return(Vm_PageIn(virtAddr, FALSE));
  1514.     */
  1515.     }
  1516. }
  1517.  
  1518.  
  1519. /*
  1520.  *----------------------------------------------------------------------
  1521.  *
  1522.  * VmMach_TLBModFault --
  1523.  *
  1524.  *    Handle a TLB modify fault.
  1525.  *
  1526.  * Results:
  1527.  *    None.
  1528.  *
  1529.  * Side effects:
  1530.  *    None.
  1531.  *
  1532.  *----------------------------------------------------------------------
  1533.  */
  1534. ReturnStatus
  1535. VmMach_TLBModFault(virtAddr)
  1536.     Address    virtAddr;
  1537. {
  1538.     Proc_ControlBlock        *procPtr;
  1539.     ReturnStatus        status;
  1540.  
  1541.     if (virtAddr >= (Address)VMMACH_VIRT_CACHED_START &&
  1542.     virtAddr < (Address)VMMACH_MAPPED_PAGE_ADDR) {
  1543.     /*
  1544.      * We shouldn't get TLB modified faults for kernel virtual
  1545.      * addresses because the modify bit was set when we validated the 
  1546.      * page.
  1547.      */
  1548.     panic("VmMach_TLBModFault: Kernel TLB mod fault\n");
  1549.     return(FAILURE);
  1550.     }
  1551.     tlbCountersPtr->slowModCount++;
  1552.     procPtr = Proc_GetCurrentProc();
  1553.     procPtr->vmPtr->machPtr->modPage = (unsigned)virtAddr >> VMMACH_PAGE_SHIFT;
  1554.     status = Vm_PageIn(virtAddr, TRUE);
  1555.     procPtr->vmPtr->machPtr->modPage = 0;
  1556.     return(status);
  1557. }
  1558.  
  1559.  
  1560. /*
  1561.  *----------------------------------------------------------------------
  1562.  *
  1563.  * VmMach_MapKernelIntoUser --
  1564.  *
  1565.  *    Unimplemented on PMAX.
  1566.  *
  1567.  * Results:
  1568.  *    FAILURE.
  1569.  *
  1570.  * Side effects:
  1571.  *    None.
  1572.  *
  1573.  *----------------------------------------------------------------------
  1574.  */
  1575. ReturnStatus
  1576. VmMach_MapKernelIntoUser()
  1577. {
  1578.     return(FAILURE);
  1579. }
  1580.  
  1581.  
  1582. /*
  1583.  *----------------------------------------------------------------------
  1584.  *
  1585.  * VmMach_Trace --
  1586.  *
  1587.  *    Virtual memory tracing.
  1588.  *
  1589.  * Results:
  1590.  *    None.
  1591.  *
  1592.  * Side effects:
  1593.  *    None.
  1594.  *
  1595.  *----------------------------------------------------------------------
  1596.  */
  1597. void
  1598. VmMach_Trace()
  1599. {
  1600. }
  1601.  
  1602.  
  1603. /*
  1604.  *----------------------------------------------------------------------
  1605.  *
  1606.  * VmMach_MakeDebugAccessible --
  1607.  *
  1608.  *    Make the given address accessible for the debugger.
  1609.  *
  1610.  * Results:
  1611.  *    TRUE if could make accessible, FALSE if couldn't.
  1612.  *
  1613.  * Side effects:
  1614.  *    None.
  1615.  *
  1616.  *----------------------------------------------------------------------
  1617.  */
  1618. Boolean
  1619. VmMach_MakeDebugAccessible(addr)
  1620.     unsigned    addr;
  1621. {
  1622.     unsigned virtPage, lowEntry, highEntry;
  1623.  
  1624.     if (addr < (unsigned)VMMACH_VIRT_CACHED_START) {
  1625.     return(addr > (unsigned)VMMACH_PHYS_CACHED_START &&
  1626.            addr < (unsigned)VMMACH_PHYS_CACHED_START + 
  1627.             vm_NumPhysPages * VMMACH_PAGE_SIZE);
  1628.     }
  1629.     if (addr > (unsigned)mach_KernEnd) {
  1630.     return(FALSE);
  1631.     }
  1632.     virtPage = addr >> VMMACH_PAGE_SHIFT;
  1633.     lowEntry = vmMach_KernelTLBMap[virtPage - VMMACH_VIRT_CACHED_START_PAGE];
  1634.     if (lowEntry == 0) {
  1635.     return(FALSE);
  1636.     }
  1637.     /*
  1638.      * Use the special reserved TLB entry (entry 0).
  1639.      */
  1640.     highEntry = (virtPage << VMMACH_TLB_VIRT_PAGE_SHIFT) |
  1641.                 (VMMACH_KERN_PID << VMMACH_TLB_PID_SHIFT);
  1642.     VmMachWriteIndexedTLB(0, lowEntry, highEntry);
  1643.     return(TRUE);
  1644. }
  1645.  
  1646. #define TLB_HASH(pid, page) \
  1647.     ((page) ^ ((pid) << (VMMACH_PID_HASH_SHIFT + VMMACH_TLB_PID_SHIFT - \
  1648.              VMMACH_BUCKET_SIZE_SHIFT))) & VMMACH_HASH_MASK_2
  1649.  
  1650.  
  1651. /*
  1652.  *----------------------------------------------------------------------
  1653.  *
  1654.  * TLBHashFind --
  1655.  *
  1656.  *    Find the entry with the given key in the hash table.
  1657.  *
  1658.  * Results:
  1659.  *    Pointer to hash table entry if found, NIL otherwise.
  1660.  *
  1661.  * Side effects:
  1662.  *    None.
  1663.  *
  1664.  *----------------------------------------------------------------------
  1665.  */
  1666. INTERNAL static TLBHashBucket *
  1667. TLBHashFind(pid, page)
  1668.     int        pid;
  1669.     unsigned    page;
  1670. {
  1671.     TLBHashBucket    *hashBucketPtr;
  1672.  
  1673.     tlbCountersPtr->numProbes++;
  1674.  
  1675.     hashBucketPtr = &vmMachTLBHashTable[TLB_HASH(pid, page)];
  1676.     if (hashBucketPtr->high == ((page << VMMACH_TLB_VIRT_PAGE_SHIFT) |
  1677.                 (pid << VMMACH_TLB_PID_SHIFT))) {
  1678.     tlbCountersPtr->numFound++;
  1679.     return(hashBucketPtr);
  1680.     } else {
  1681.     return((TLBHashBucket *)NIL);
  1682.     }
  1683. }
  1684.  
  1685.  
  1686. /*
  1687.  *----------------------------------------------------------------------
  1688.  *
  1689.  * TLBHashDelete --
  1690.  *
  1691.  *    Find the entry with the given key in the hash table and delete it.
  1692.  *
  1693.  * Results:
  1694.  *    None.
  1695.  *
  1696.  * Side effects:
  1697.  *    Entry may be deleted from the hash table.
  1698.  *
  1699.  *----------------------------------------------------------------------
  1700.  */
  1701. INTERNAL static void
  1702. TLBHashDelete(pid, page)
  1703.     int        pid;
  1704.     unsigned    page;
  1705. {
  1706.     TLBHashBucket    *hashBucketPtr;
  1707.  
  1708.     hashBucketPtr = &vmMachTLBHashTable[TLB_HASH(pid, page)];
  1709.     if (hashBucketPtr->high == ((page << VMMACH_TLB_VIRT_PAGE_SHIFT) |
  1710.                 (pid << VMMACH_TLB_PID_SHIFT))) {
  1711.     hashBucketPtr->high = 0;
  1712.     List_Remove((List_Links *)hashBucketPtr);
  1713.     }
  1714. }
  1715.  
  1716.  
  1717. /*
  1718.  *----------------------------------------------------------------------
  1719.  *
  1720.  * TLBHashInsert --
  1721.  *
  1722.  *    Insert the entry in the hash table if it is not already there.
  1723.  *
  1724.  * Results:
  1725.  *    None.
  1726.  *
  1727.  * Side effects:
  1728.  *    Entry may be added to the hash table.
  1729.  *
  1730.  *----------------------------------------------------------------------
  1731.  */
  1732. INTERNAL static void
  1733. TLBHashInsert(pid, page, lowReg, hiReg)
  1734.     int        pid;
  1735.     unsigned    page;
  1736.     unsigned    lowReg;
  1737.     unsigned    hiReg;
  1738. {
  1739.     TLBHashBucket    *hashBucketPtr;
  1740.  
  1741.     if (pid == VMMACH_KERN_PID) {
  1742.     /*
  1743.      * Don't insert any entries for the kernel pid.  This will only 
  1744.      * happen because a process with no VM is doing a CopyOutProc.
  1745.      */
  1746.     return;
  1747.     }
  1748.  
  1749.     tlbCountersPtr->numInserts++;
  1750.     hashBucketPtr = &vmMachTLBHashTable[TLB_HASH(pid, page)];
  1751.     if (hashBucketPtr->high == hiReg) {
  1752.     return;
  1753.     }
  1754.     if (hashBucketPtr->high != 0) {
  1755.     tlbCountersPtr->numCollisions++;
  1756.     List_Remove((List_Links *)hashBucketPtr);
  1757.     }
  1758.     hashBucketPtr->low = lowReg;
  1759.     hashBucketPtr->high = hiReg;
  1760.     List_Insert((List_Links *)hashBucketPtr,
  1761.         LIST_ATREAR(&pidListElems[pid].tlbList));
  1762. }
  1763.  
  1764.  
  1765. /*
  1766.  *----------------------------------------------------------------------
  1767.  *
  1768.  * TLBHashFlushPID --
  1769.  *
  1770.  *    Flush all entries for the given PID from the hash table.
  1771.  *
  1772.  * Results:
  1773.  *    None.
  1774.  *
  1775.  * Side effects:
  1776.  *    All entries for the given PID are flushed from the hash table.
  1777.  *
  1778.  *----------------------------------------------------------------------
  1779.  */
  1780. INTERNAL static void
  1781. TLBHashFlushPID(pid)
  1782.     int    pid;
  1783. {
  1784.     PIDListElem        *pidPtr;
  1785.     TLBHashBucket    *hashBucketPtr;
  1786.  
  1787.     pidPtr = &pidListElems[pid];
  1788.     while (!List_IsEmpty(&pidPtr->tlbList)) {
  1789.     hashBucketPtr = (TLBHashBucket *)List_First(&pidPtr->tlbList);
  1790.     List_Remove((List_Links *)hashBucketPtr);
  1791.     hashBucketPtr->high = 0;
  1792.     }
  1793. }
  1794.  
  1795.  
  1796. /*
  1797.  *----------------------------------------------------------------------
  1798.  *
  1799.  * VmMach_MakeNonCacheable --
  1800.  *
  1801.  *    Make the given page non-cacheable.
  1802.  *
  1803.  * Results:
  1804.  *    None.
  1805.  *
  1806.  * Side effects:
  1807.  *    None.
  1808.  *
  1809.  *----------------------------------------------------------------------
  1810.  */
  1811. ENTRY void
  1812. VmMach_MakeNonCacheable(procPtr, addr)
  1813.     Proc_ControlBlock    *procPtr;
  1814.     Address        addr;
  1815. {
  1816.     TLBHashBucket    *bucketPtr;
  1817.  
  1818.     MASTER_LOCK(vmMachMutexPtr);
  1819.  
  1820.     VmMachFlushTLB();
  1821.     bucketPtr = TLBHashFind(procPtr->vmPtr->machPtr->pid,
  1822.                 (unsigned)addr >> VMMACH_PAGE_SHIFT);
  1823.     if (bucketPtr != (TLBHashBucket *)NIL) {
  1824.     bucketPtr->low |= VMMACH_TLB_NON_CACHEABLE_BIT;
  1825.     } else {
  1826.     printf("VmMach_MakeNonCacheable: Not found\n");
  1827.     }
  1828.  
  1829.     MASTER_UNLOCK(vmMachMutexPtr);
  1830. }
  1831.  
  1832.  
  1833. /*
  1834.  *----------------------------------------------------------------------
  1835.  *
  1836.  * VmMach_UserMap --
  1837.  *
  1838.  *    Map the given range of kernel physical addresses into the
  1839.  *    given user's virtual address space.  This is only used for the X
  1840.  *    server and thus    there can only be one user mapping at once.
  1841.  *
  1842.  * Results:
  1843.  *    None.
  1844.  *
  1845.  * Side effects:
  1846.  *    None.
  1847.  *
  1848.  *----------------------------------------------------------------------
  1849.  */
  1850. Address
  1851. VmMach_UserMap(numBytes, physAddr, firstTime)
  1852.     int        numBytes;
  1853.     Address    physAddr;
  1854.     Boolean    firstTime;
  1855. {
  1856.     int        i;
  1857.     Address    retAddr;
  1858.     unsigned    firstPhysPage;
  1859.     unsigned    lastPhysPage;
  1860.  
  1861.     if (firstTime) {
  1862.     if (userMapped) {
  1863.         return((Address)NIL);
  1864.     }
  1865.     bzero((char *)userMappingTable, sizeof(userMappingTable));
  1866.     userMapIndex = 0;
  1867.     userMapped = TRUE;
  1868.     mappedProcPtr = Proc_GetCurrentProc();
  1869.     }
  1870.     retAddr = (Address) (VMMACH_USER_MAPPING_BASE_ADDR +
  1871.                          userMapIndex * VMMACH_PAGE_SIZE + 
  1872.              ((unsigned)physAddr & VMMACH_OFFSET_MASK));
  1873.     firstPhysPage = (unsigned)physAddr >> VMMACH_PAGE_SHIFT;
  1874.     lastPhysPage = (unsigned)(physAddr + numBytes - 1) >> VMMACH_PAGE_SHIFT;
  1875.     for (i = firstPhysPage; i <= lastPhysPage; i++) {
  1876.     userMappingTable[userMapIndex] = (i << VMMACH_TLB_PHYS_PAGE_SHIFT) |
  1877.                  VMMACH_TLB_VALID_BIT | VMMACH_TLB_MOD_BIT;
  1878.     userMapIndex++;
  1879.     if (i <= lastPhysPage && userMapIndex == VMMACH_USER_MAPPING_PAGES) {
  1880.         return((Address)NIL);
  1881.     }
  1882.     }
  1883.  
  1884.     return(retAddr);
  1885. }
  1886.  
  1887.  
  1888. /*
  1889.  *----------------------------------------------------------------------
  1890.  *
  1891.  * VmMach_UserUnmap --
  1892.  *
  1893.  *    Unmap all pages mapped into a user's address space.
  1894.  *
  1895.  * Results:
  1896.  *    None.
  1897.  *
  1898.  * Side effects:
  1899.  *    None.
  1900.  *
  1901.  *----------------------------------------------------------------------
  1902.  */
  1903. ENTRY void
  1904. VmMach_UserUnmap()
  1905. {
  1906.     int            pid;
  1907.     Proc_ControlBlock    *procPtr;
  1908.  
  1909.     if (!userMapped) {
  1910.     return;
  1911.     }
  1912.     userMapped = FALSE;
  1913.     procPtr = Proc_GetCurrentProc();
  1914.     if (procPtr != mappedProcPtr) {
  1915.     printf("VmMach_UserUnmap: Different process is unmapping\n");
  1916.     }
  1917.     mappedProcPtr = (Proc_ControlBlock *)NIL;
  1918.     pid = procPtr->vmPtr->machPtr->pid;
  1919.     if (pid != VMMACH_INV_PID && pid != VMMACH_KERN_PID) {
  1920.     MASTER_LOCK(vmMachMutexPtr);
  1921.     TLBHashFlushPID(pid);
  1922.     MASTER_UNLOCK(vmMachMutexPtr);
  1923.     }
  1924. }
  1925.  
  1926.  
  1927. #define ALLOC(x,s)    (sharedData->allocVector[(x)]=s)
  1928. #define FREE(x)        (sharedData->allocVector[(x)]=0)
  1929. #define SIZE(x)        (sharedData->allocVector[(x)])
  1930. #define ISFREE(x)    (sharedData->allocVector[(x)]==0)
  1931.  
  1932.  
  1933.  
  1934. /*
  1935.  * ----------------------------------------------------------------------------
  1936.  *
  1937.  * VmMach_Alloc --
  1938.  *
  1939.  *      Allocates a region of shared memory;
  1940.  *
  1941.  * Results:
  1942.  *      SUCCESS if the region can be allocated.
  1943.  *    The starting address is returned in addr.
  1944.  *
  1945.  * Side effects:
  1946.  *      The allocation vector is updated.
  1947.  *
  1948.  * ----------------------------------------------------------------------------
  1949.  */
  1950. static ReturnStatus
  1951. VmMach_Alloc(sharedData, regionSize, addr)
  1952.     VmMach_SharedData    *sharedData;    /* Pointer to shared memory info.  */
  1953.     int            regionSize;    /* Size of region to allocate. */
  1954.     Address        *addr;        /* Address of region. */
  1955. {
  1956.     int numBlocks = (regionSize+VMMACH_SHARED_BLOCK_SIZE-1) /
  1957.         VMMACH_SHARED_BLOCK_SIZE;
  1958.     int i, blockCount, firstBlock;
  1959.  
  1960.     if (sharedData->allocVector == (int *)NULL || sharedData->allocVector ==
  1961.         (int *)NIL) {
  1962.     dprintf("VmMach_Alloc: allocVector uninitialized!\n");
  1963.     }
  1964.  
  1965.     /*
  1966.      * Loop through the alloc vector until we find numBlocks free blocks
  1967.      * consecutively.
  1968.      */
  1969.     blockCount = 0;
  1970.     for (i=sharedData->allocFirstFree;
  1971.         i<=VMMACH_SHARED_NUM_BLOCKS-1 && blockCount<numBlocks;i++) {
  1972.     if (ISFREE(i)) {
  1973.         blockCount++;
  1974.     } else {
  1975.         blockCount = 0;
  1976.         if (i==sharedData->allocFirstFree) {
  1977.         sharedData->allocFirstFree++;
  1978.         }
  1979.     }
  1980.     }
  1981.     if (blockCount < numBlocks) {
  1982.     dprintf("VmMach_Alloc: got %d blocks of %d of %d total\n",
  1983.         blockCount,numBlocks,VMMACH_SHARED_NUM_BLOCKS);
  1984.     return VM_NO_SEGMENTS;
  1985.     }
  1986.     firstBlock = i-blockCount;
  1987.     if (firstBlock == sharedData->allocFirstFree) {
  1988.     sharedData->allocFirstFree += blockCount;
  1989.     }
  1990.     *addr = (Address)(firstBlock*VMMACH_SHARED_BLOCK_SIZE +
  1991.         VMMACH_SHARED_START_ADDR);
  1992.     for (i = firstBlock; i<firstBlock+numBlocks; i++) {
  1993.     ALLOC(i,numBlocks);
  1994.     }
  1995.     dprintf("VmMach_Alloc: got %d blocks at %d (%x)\n",
  1996.         numBlocks,firstBlock,*addr);
  1997.     return SUCCESS;
  1998. }
  1999.  
  2000.  
  2001. /*
  2002.  * ----------------------------------------------------------------------------
  2003.  *
  2004.  * VmMach_Unalloc --
  2005.  *
  2006.  *      Frees a region of shared address space.
  2007.  *
  2008.  * Results:
  2009.  *      None.
  2010.  *
  2011.  * Side effects:
  2012.  *      The allocation vector is updated.
  2013.  *
  2014.  * ----------------------------------------------------------------------------
  2015.  */
  2016.  
  2017. static void
  2018. VmMach_Unalloc(sharedData, addr)
  2019.     VmMach_SharedData    *sharedData;    /* Pointer to shared memory info. */
  2020.     Address    addr;        /* Address of region. */
  2021. {
  2022.     int firstBlock = ((int)addr-VMMACH_SHARED_START_ADDR) /
  2023.         VMMACH_SHARED_BLOCK_SIZE;
  2024.     int numBlocks = SIZE(firstBlock);
  2025.     int i;
  2026.  
  2027.     dprintf("VmMach_Unalloc: freeing %d blocks at %x\n",numBlocks,addr);
  2028.     if (firstBlock < sharedData->allocFirstFree) {
  2029.     sharedData->allocFirstFree = firstBlock;
  2030.     }
  2031.     for (i=0;i<numBlocks;i++) {
  2032.     if (ISFREE(i+firstBlock)) {
  2033.         printf("Freeing free shared address %d %d %d\n",i,i+firstBlock,
  2034.             (int)addr);
  2035.         return;
  2036.     }
  2037.     FREE(i+firstBlock);
  2038.     }
  2039. }
  2040.  
  2041. /*
  2042.  * ----------------------------------------------------------------------------
  2043.  *
  2044.  * VmMach_SharedStartAddr --
  2045.  *
  2046.  *      Determine the starting address for a shared segment.
  2047.  *
  2048.  * Results:
  2049.  *      Returns the proper start address for the segment.
  2050.  *
  2051.  * Side effects:
  2052.  *      Allocates part of the shared address space.
  2053.  *
  2054.  * ----------------------------------------------------------------------------
  2055.  */
  2056. ReturnStatus
  2057. VmMach_SharedStartAddr(procPtr,size,reqAddr, fixed)
  2058.     Proc_ControlBlock   *procPtr;
  2059.     int             size;           /* Length of shared segment. */
  2060.     Address         *reqAddr;        /* Requested start address. */
  2061.     int             fixed;          /* 1 if fixed address requested. */
  2062. {
  2063.     int numBlocks = (size+VMMACH_SHARED_BLOCK_SIZE-1) /
  2064.             VMMACH_SHARED_BLOCK_SIZE;
  2065.     int firstBlock = (((int)*reqAddr)-VMMACH_SHARED_START_ADDR+
  2066.             VMMACH_SHARED_BLOCK_SIZE-1) /
  2067.             VMMACH_SHARED_BLOCK_SIZE;
  2068.     int i;
  2069.     VmMach_SharedData   *sharedData = &procPtr->vmPtr->machPtr->sharedData;
  2070.  
  2071.     if (fixed==0) {
  2072.         return VmMach_Alloc(sharedData, size, reqAddr);
  2073.     } else {
  2074.         for (i = firstBlock; i<firstBlock+numBlocks; i++) {
  2075.             if (i>0) {
  2076.                 ALLOC(i,numBlocks);
  2077.             }
  2078.         }
  2079.         return SUCCESS;
  2080.     }
  2081. }
  2082.  
  2083. /*
  2084.  * ----------------------------------------------------------------------------
  2085.  *
  2086.  * VmMach_SharedProcStart --
  2087.  *
  2088.  *      Perform machine dependent initialization of shared memory
  2089.  *    for this process.
  2090.  *
  2091.  * Results:
  2092.  *      None.
  2093.  *
  2094.  * Side effects:
  2095.  *      The storage allocation structures are initialized.
  2096.  *
  2097.  * ----------------------------------------------------------------------------
  2098.  */
  2099. void
  2100. VmMach_SharedProcStart(procPtr)
  2101.     Proc_ControlBlock    *procPtr;
  2102. {
  2103.     VmMach_SharedData    *sharedData = &procPtr->vmPtr->machPtr->sharedData;
  2104.     dprintf("VmMach_SharedProcStart: initializing proc's allocVector\n");
  2105.     if (sharedData->allocVector != (int *)NIL) {
  2106.     panic("VmMach_SharedProcStart: allocVector not NIL\n");
  2107.     }
  2108.     sharedData->allocVector =
  2109.         (int *)malloc(VMMACH_SHARED_NUM_BLOCKS*sizeof(int));
  2110.     sharedData->allocFirstFree = 0;
  2111.     bzero((Address) sharedData->allocVector, VMMACH_SHARED_NUM_BLOCKS*
  2112.         sizeof(int));
  2113.     procPtr->vmPtr->sharedStart = (Address) VMMACH_SHARED_START_ADDR;
  2114.     procPtr->vmPtr->sharedEnd = (Address) VMMACH_SHARED_START_ADDR+
  2115.         VMMACH_USER_SHARED_PAGES*VMMACH_PAGE_SIZE;
  2116. }
  2117.  
  2118. /*
  2119.  * ----------------------------------------------------------------------------
  2120.  *
  2121.  * VmMach_SharedSegFinish --
  2122.  *
  2123.  *      Perform machine dependent cleanup of shared memory
  2124.  *    for this segment.
  2125.  *
  2126.  * Results:
  2127.  *      None.
  2128.  *
  2129.  * Side effects:
  2130.  *      The storage allocation structures are freed.
  2131.  *
  2132.  * ----------------------------------------------------------------------------
  2133.  */
  2134. void
  2135. VmMach_SharedSegFinish(procPtr,addr)
  2136.     Proc_ControlBlock    *procPtr;
  2137.     Address        addr;
  2138. {
  2139.     VmMach_Unalloc(&procPtr->vmPtr->machPtr->sharedData,addr);
  2140. }
  2141.  
  2142. /*
  2143.  * ----------------------------------------------------------------------------
  2144.  *
  2145.  * VmMach_SharedProcFinish --
  2146.  *
  2147.  *      Perform machine dependent cleanup of shared memory
  2148.  *    for this process.
  2149.  *
  2150.  * Results:
  2151.  *      None.
  2152.  *
  2153.  * Side effects:
  2154.  *      The storage allocation structures are freed.
  2155.  *
  2156.  * ----------------------------------------------------------------------------
  2157.  */
  2158. void
  2159. VmMach_SharedProcFinish(procPtr)
  2160.     Proc_ControlBlock    *procPtr;
  2161. {
  2162.     dprintf("VmMach_SharedProcFinish: freeing process's allocVector\n");
  2163.     free((Address)procPtr->vmPtr->machPtr->sharedData.allocVector);
  2164.     procPtr->vmPtr->machPtr->sharedData.allocVector;
  2165.     procPtr->vmPtr->machPtr->sharedData.allocVector = (int *)NIL;
  2166. }
  2167.  
  2168. /*
  2169.  * ----------------------------------------------------------------------------
  2170.  *
  2171.  * VmMach_CopySharedMem --
  2172.  *
  2173.  *      Copies machine-dependent shared memory data structures to handle
  2174.  *    a fork.
  2175.  *
  2176.  * Results:
  2177.  *      None.
  2178.  *
  2179.  * Side effects:
  2180.  *      The new process gets a copy of the shared memory structures.
  2181.  *
  2182.  * ----------------------------------------------------------------------------
  2183.  */
  2184. void
  2185. VmMach_CopySharedMem(parentProcPtr, childProcPtr)
  2186.     Proc_ControlBlock   *parentProcPtr; /* Parent process. */
  2187.     Proc_ControlBlock   *childProcPtr;  /* Child process. */
  2188. {
  2189.     VmMach_SharedData    *childSharedData =
  2190.         &childProcPtr->vmPtr->machPtr->sharedData;
  2191.     VmMach_SharedData    *parentSharedData =
  2192.         &parentProcPtr->vmPtr->machPtr->sharedData;
  2193.  
  2194.     VmMach_SharedProcStart(childProcPtr);
  2195.  
  2196.     bcopy(parentSharedData->allocVector, childSharedData->allocVector,
  2197.         VMMACH_SHARED_NUM_BLOCKS*sizeof(int));
  2198.     childSharedData->allocFirstFree = parentSharedData->allocFirstFree;
  2199. }
  2200.  
  2201. /*
  2202.  * ----------------------------------------------------------------------------
  2203.  *
  2204.  * VmMach_LockCachePage --
  2205.  *
  2206.  *      Perform machine dependent locking of a kernel resident file cache
  2207.  *    page.
  2208.  *
  2209.  * Results:
  2210.  *      None.
  2211.  *
  2212.  * Side effects:
  2213.  *
  2214.  * ----------------------------------------------------------------------------
  2215.  */
  2216. void
  2217. VmMach_LockCachePage(kernelAddress)
  2218.     Address    kernelAddress;    /* Address on page to lock. */
  2219. {
  2220.     /*
  2221.      * Ds3100 leaves file cache pages always available so there is no need to
  2222.      * lock or unlock them.
  2223.      */
  2224.     return;
  2225. }
  2226.  
  2227. /*
  2228.  * ----------------------------------------------------------------------------
  2229.  *
  2230.  * VmMach_UnlockCachePage --
  2231.  *
  2232.  *      Perform machine dependent unlocking of a kernel resident page.
  2233.  *
  2234.  * Results:
  2235.  *      None.
  2236.  *
  2237.  * Side effects:
  2238.  *
  2239.  * ----------------------------------------------------------------------------
  2240.  */
  2241. void
  2242. VmMach_UnlockCachePage(kernelAddress)
  2243.     Address    kernelAddress;    /* Address on page to unlock. */
  2244. {
  2245.     /*
  2246.      * Ds3100 leaves file cache pages always available so there is no need to
  2247.      * lock or unlock them.
  2248.      */
  2249.     return;
  2250. }
  2251.  
  2252.